import * as ol from "ol";
import {
  clone,
  createEmpty,
  extend,
  extendCoordinates,
  getBottomRight,
  getTopLeft,
  isEmpty,
} from "ol/extent";
import type { Extent } from "ol/extent";
import { parseLngLat } from "./utils";
import { fromLonLat } from "ol/proj";
import { LngLat } from "./types";
import { queryFeatures } from "./feature";
/**
 * @description: 通过经纬度获取范围
 * @param {Array<LngLat>} coordinates 经纬度数组
 * @returns {Extent}
 */
export const queryExtentByCoordinates = (coordinates: LngLat[]): Extent => {
  let extent = createEmpty();
  extent = extendCoordinates(
    extent,
    coordinates
      .map((lnglat) => parseLngLat(lnglat))
      .filter((lnglat) => !!lnglat)
      .map((coordinate) => fromLonLat(coordinate as number[]))
  );

  return extent;
};

/**
 * @description: 通过元素获取范围
 * @param {ol.Feature|Array<ol.Feature>} features 元素列表
 * @returns {Extent}
 */
export const queryExtentByFeatures = (
  features: ol.Feature[] | ol.Feature
): Extent => {
  let extent = createEmpty();
  (Array.isArray(features) ? features : [features]).forEach((feature) => {
    const geometry = feature.getGeometry();
    if (geometry) {
      extent = extend(extent, geometry.getExtent());
    }
  });

  return extent;
};
/**
 * @description: 通过查询获取范围
 * @param {Object} query 查询参数
 * @returns {Extent.Extent}
 */
export const queryExtentByQuery = (query: {
  features?: string[];
  layers?: string[];
}): Extent => {
  let extent = createEmpty();
  queryFeatures(query).forEach((feature) => {
    const geometry = feature.getGeometry();
    if (geometry) {
      extent = extend(extent, geometry.getExtent());
    }
  });

  return extent;
};
/**
 * @description: 范围偏移转换
 * @param {Extent} extent 范围
 * @param {Array<number>} offset 偏移量
 * @returns {Extent}
 */
export const transformExtentOffset = (
  extent: Extent,
  offset: number[] = []
): Extent => {
  const result = clone(extent);

  if (isEmpty(result)) {
    return clone(extent);
  }

  const [offsetX, offsetY] = offset;
  let [left, top] = getTopLeft(extent);
  let [right, bottom] = getBottomRight(extent);

  if (typeof offsetX === "number") {
    left += offsetX;
    right += offsetX;
  }

  if (typeof offsetY === "number") {
    top += offsetY;
    bottom += offsetY;
  }

  return queryExtentByCoordinates([
    [left, top],
    [right, bottom],
  ]);
};

/**
 * @description: 范围扩张转换
 * @param {Extent} extent 范围
 * @param {Array<number>} size 扩张大小，值为经纬度，分别代表上、右、下、左的扩张大小
 * @returns {Extent}
 */
export const transformExtentExpand = (
  extent: Extent,
  size: number[] = []
): Extent => {
  const result = clone(extent);

  if (isEmpty(result)) {
    return clone(extent);
  }

  const [topSize = 0, rightSize = 0, bottomSize = 0, leftSize = 0] = size;
  let [left, top] = getTopLeft(extent);
  let [right, bottom] = getBottomRight(extent);

  left += leftSize;
  right += rightSize;
  top += topSize;
  bottom += bottomSize;

  return queryExtentByCoordinates([
    [left, top],
    [right, bottom],
  ]);
};
